package com.yelobblog.yelobblog.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yelobblog.yelobblog.common.exception.ApiException;
import com.yelobblog.yelobblog.common.exception.ErrorEnum;
import com.yelobblog.yelobblog.common.untils.ThreadLocalUtil;
import com.yelobblog.yelobblog.common.untils.articlesStatusEnum;
import com.yelobblog.yelobblog.domain.Vo.articlesVo;
import com.yelobblog.yelobblog.domain.entity.articles;
import com.yelobblog.yelobblog.mapper.articlesMapper;
import com.yelobblog.yelobblog.service.articlesService;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.yelobblog.yelobblog.common.untils.userStatusEnum;

import java.util.List;
import java.util.Map;

@Service
public class articlesServiceimpl extends ServiceImpl<articlesMapper, articles> implements articlesService {
    @Resource
    private articlesMapper articlesMapper;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Override
    public void recordViewCount(Integer articleId, String userIp) {
        // 1. 生成Redis键（例如：article:view:文章ID）
        String viewKey = "article:view:" + articleId;
        // 2. 使用Redis的HyperLogLog记录唯一IP（去重统计UV）
        Long added = redisTemplate.opsForHyperLogLog().add(viewKey + ":uv", userIp);
        if (added == 1) {
            // IP 是新记录，可以在此处添加额外逻辑，比如更新实时统计等
            System.out.println("新的唯一访问 IP: " + userIp);
        } else {
            // IP 已存在记录
            System.out.println("IP 已存在记录: " + userIp);
            return;
        }
        // 4. 定期同步到数据库（避免频繁写库）
        scheduleSyncViewCountToDB(articleId);
    }

    // 定时同步浏览量到数据库的方法
    private void scheduleSyncViewCountToDB(Integer articleId) {
        articlesMapper.addViewCount(articleId);
    }

    @Override
    public Page<articlesVo> searchArticles(int pageNum, int pageSize, String keyword) {
        Page<?> page = new Page<>(pageNum, pageSize);
        return articlesMapper.searchArticles(page, keyword, articlesStatusEnum.PUBLIC.getCode());
    }

    @Override
    public articlesVo selectById(Integer id) {
        return articlesMapper.selectById(id);
    }

    @Override
    public Page<articlesVo> selectList(Integer pageNum, Integer pageSize) {
        return articlesMapper.selectList(new Page<>(pageNum, pageSize),articlesStatusEnum.PUBLIC.getCode());
    }
    @Override
    public List<articlesVo> selectListByUpdateTime() {
        return articlesMapper.selectListByUpdateTime();
    }
    @Override
    public List<articlesVo> selectListByViewCount() {
        return articlesMapper.selectListByViewCount();
    }

    @Override
    public Page<articlesVo> selectListByCategoryId(Integer pageNum, Integer pageSize, Integer categoryId) {
        return articlesMapper.selectListByCategoryId(new Page<>(pageNum, pageSize), categoryId,articlesStatusEnum.PUBLIC.getCode());
    }
    @Override
    public Page<articlesVo> selectPublicByAuthorId(Integer pageNum, Integer pageSize, Integer authorId) {
        return articlesMapper.selectListByAuthorId(new Page<>(pageNum, pageSize), authorId,articlesStatusEnum.PUBLIC.getCode());
    }
    @Override
    public Page<articlesVo> selectPrivateByAuthorId(Integer pageNum, Integer pageSize) {
        Map<String,Object> claims= ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");
        return articlesMapper.selectListByAuthorId(new Page<>(pageNum, pageSize), userId,articlesStatusEnum.PRIVATE.getCode());
    }
    @Override
    public Page<articlesVo> selectDraftByAuthorId(Integer pageNum, Integer pageSize) {
        Map<String,Object> claims= ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");
        return articlesMapper.selectListByAuthorId(new Page<>(pageNum, pageSize), userId,articlesStatusEnum.DRAFT.getCode());
    }
    @Override
    public Page<articlesVo> selectDeletedByAuthorId(Integer pageNum, Integer pageSize) {
        Map<String,Object> claims= ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");
        return articlesMapper.selectListByAuthorId(new Page<>(pageNum, pageSize), userId,articlesStatusEnum.DELETED.getCode());
    }
//    @Override

    @Override
    public void insert(String title, String description, Integer categoryId) {
        Map<String,Object> claims= ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");
        Integer role = (Integer) claims.get("role");
        if (role.equals(userStatusEnum.NORMAL.getCode())) {
            throw new ApiException(ErrorEnum.PERMISSION_DENIED.getErrorCode(), ErrorEnum.PERMISSION_DENIED.getErrorMsg());
        }
        articlesMapper.insert(title,description,"",categoryId,userId);
    }
    @Override
    public void update(articles articles){
        Map<String,Object> claims= ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");
        Integer role = (Integer) claims.get("role");
        if(!role.equals(userStatusEnum.SUPERUSER.getCode())) {
            if (!role.equals(userStatusEnum.FORMAL.getCode()) || !articles.getAuthorId().equals(userId)) {
                throw new ApiException(ErrorEnum.PERMISSION_DENIED.getErrorCode(), ErrorEnum.PERMISSION_DENIED.getErrorMsg());
            }
        }
        articlesMapper.updateById(articles);
    }

    @Override
    public void deleteById(Integer id){
        Map<String,Object> claims= ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");
        Integer role = (Integer) claims.get("role");
        if(!role.equals(userStatusEnum.SUPERUSER.getCode())) {
            if (!role.equals(userStatusEnum.FORMAL.getCode()) || !articlesMapper.selectById(id).getAuthorId().equals(userId)) {
                throw new ApiException(ErrorEnum.PERMISSION_DENIED.getErrorCode(), ErrorEnum.PERMISSION_DENIED.getErrorMsg());
            }
        }
        articlesMapper.updateStatus(id, articlesStatusEnum.DELETED.getCode());
    }
}
